/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Graph.java
 *
 * Created on 28-Apr-2010, 15:04:37
 */

package phd.dupenois.changeidentifiers.optimisation.singlepattern.frames;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.JScrollPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import phd.dupenois.changeidentifiers.ChangeIdentifierSet;

/**
 *
 * @author Max
 */
public class GraphFrame extends javax.swing.JFrame {
    private GraphPanel graph;
    private JFileChooser saveGraphChooser;
    private JFileChooser saveResultsChooser;
    private StyledDocument setDetailsStyledDoc;
    private int maxGeneration;
    private int currentGeneration;
    private ResultSaveInterface resultSaver;
    /** Creates new form Graph
     * @param graph
     * @param resultSaver
     */
    public GraphFrame(GraphPanel graph, ResultSaveInterface resultSaver) {
        initComponents();
        this.resultSaver = resultSaver;
        this.graph = graph;
        this.graph.setFrame(this);
        this.graphPanel.setLayout(new GridLayout(1,1));
        this.graphPanel.add(graph);
        this.saveGraphMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                openSaveGraphDialog();
            }
        });

        saveGraphChooser = new JFileChooser();
        saveGraphChooser.setMultiSelectionEnabled(false);
//        saveFileChooser.setFileFilter(new ChangeIdentifierSetFileFilter());
        saveGraphChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);


        this.saveResultsMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                openSaveResultsDialog();
            }
        });


        saveResultsChooser = new JFileChooser();
        saveResultsChooser.setMultiSelectionEnabled(false);
//        saveFileChooser.setFileFilter(new ChangeIdentifierSetFileFilter());
        saveResultsChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);



        setComponentSize(this, new Dimension(500,400));
        setDetailsStyledDoc = setDetailsTextPane.getStyledDocument();
        addStylesToDocument(setDetailsStyledDoc);

        Dimension detailsDisplayDimension = new Dimension(300, 400);
        setComponentSize(detailsDisplayPanel, detailsDisplayDimension);

//        Dimension detailsDisplayDimension = new Dimension(300, 400);
//        setComponentSize(setDetailsScrollPane.getViewport(), detailsDisplayDimension);

//        Dimension detailsTextPaneDimension = new Dimension(600, 400);
//        setComponentSize(setDetailsTextPane, detailsTextPaneDimension);

    }
//    public static void setScrollComponentSize(JScrollPane component, Dimension dim){
//        component.getViewport().setPdim);
//        component.setPreferredSize(dim);
//        component.setMinimumSize(dim);

//        component.setMaximumSize(dim);
//    }
    public static void setComponentSize(Component component, Dimension dim){
        component.setSize(dim);
        component.setPreferredSize(dim);
        component.setMinimumSize(dim);
        component.setMaximumSize(dim);
    }

    public void openSaveResultsDialog(){
        int returnVal = saveResultsChooser.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File directory;
            if(saveResultsChooser.getSelectedFile()==null){
                directory = saveResultsChooser.getCurrentDirectory();
            }else{
                directory = saveResultsChooser.getSelectedFile();
            }
            try {
                if(!directory.isDirectory()){
                    boolean makeDirs = directory.mkdirs();
                    if(!makeDirs){
                        error("Cannot create directory "+directory.getCanonicalPath());
                    }
                }
                if (this.resultSaver.saveResults(directory)) {
                    message("Saved Results to " + directory.getAbsolutePath());
                } else {
                    error("Failed to save Results to " + directory.getAbsolutePath());
                }
            } catch (Exception e) {
                error("Failed to save Results to "+directory.getAbsolutePath()+
                        " ["+e.getClass().getSimpleName()+"] '"+e.getMessage()+"'");
            }
        }

    }

    public void openSaveGraphDialog(){
        int returnVal = saveGraphChooser.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = saveGraphChooser.getSelectedFile();
            int decimal = file.getName().lastIndexOf('.');
            String ext;
            if(decimal > -1 && decimal < file.getName().length()){
                ext = file.getName().substring(decimal+1);
            }else{
                file = new File(file.getAbsolutePath()+".png");
                ext = "png";
            }
            if(!ext.toLowerCase().matches("^(png)|(gif)|(jpg)$")){
                int extIndex = file.getName().lastIndexOf("."+ext);
                file = new File(file.getAbsolutePath().substring(0, extIndex)+".png");
                ext = "png";
            }
            try {
                this.graph.writeImage(file, ext);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        
    }

    public void displaySetDetails(double timeTaken, double error, ChangeIdentifierSet set){
        clearSetDetailsTextPane();
        appendSetDetailsLine(new String[][]{
            new String[]{"Error: ","message"},
            new String[]{error+"","regular"}
        });
        appendSetDetailsLine(new String[][]{
            new String[]{"Time Taken: ","message"},
            new String[]{timeTaken+"","regular"}
        });
        appendSetDetailsLine(new String[][]{
            new String[]{"Set: ","success"},
            new String[]{set.getName()+" "+set.getVersion(),"regular"}
        });
        appendSetDetailsText(set.toXMLString(), "regular");
    }
    private void appendSetDetailsLine(String[][] line){
        //boolean scrollBarAtEnd = (outputTextPane.getCaretPosition()>outputStyledDoc.getLength()-15);
        boolean scrollBarAtEnd = (setDetailsScrollPane.getVerticalScrollBar().getValue()+setDetailsScrollPane.getVerticalScrollBar().getHeight()>
                setDetailsScrollPane.getVerticalScrollBar().getMaximum()-50);
//        System.out.println(outputScrollPane.getVerticalScrollBar().getValue()+" :: "+outputScrollPane.getVerticalScrollBar().getMaximum());
        try {
            for(String[] section : line){
                setDetailsStyledDoc.insertString(setDetailsStyledDoc.getLength(), section[0], setDetailsStyledDoc.getStyle(section[1]));
            }
            setDetailsStyledDoc.insertString(setDetailsStyledDoc.getLength(), "\n\n", setDetailsStyledDoc.getStyle("regular"));
            
        } catch (BadLocationException ex) {
        }
        if(!haltScrollOnManualUse || scrollBarAtEnd){
            setDetailsTextPane.setCaretPosition(setDetailsStyledDoc.getLength());
        }
    }
    public void error(String error){
        appendSetDetailsText(error, "error");
    }
    public void message(String message){
        appendSetDetailsText(message, "message");
    }
    public void warning(String warning){
        appendSetDetailsText(warning, "warning");
    }
    public void success(String success){
        appendSetDetailsText(success, "success");
    }
    private void addStylesToDocument(StyledDocument doc){
        Style def = StyleContext.getDefaultStyleContext().
                        getStyle(StyleContext.DEFAULT_STYLE);

        Style regular = doc.addStyle("regular", def);
        StyleConstants.setFontSize(regular, 12);
        StyleConstants.setFontFamily(def, "SansSerif");

        Style s = doc.addStyle("error", regular);
        StyleConstants.setBold(s, true);
        StyleConstants.setForeground(s, new Color(200, 0, 0, 255));;

        s = doc.addStyle("message", regular);
        StyleConstants.setForeground(s, new Color(0, 0, 200, 255));

        s = doc.addStyle("warning", regular);
        StyleConstants.setItalic(s, true);
        StyleConstants.setForeground(s, new Color(255, 134, 0, 255));

        s = doc.addStyle("success", regular);
        StyleConstants.setBold(s, true);
        StyleConstants.setForeground(s, new Color(47, 165, 61, 255));

    }
    private boolean haltScrollOnManualUse = false;
    public void haltScrollOnManualUse(){
        this.haltScrollOnManualUse = true;
    }
    private void appendSetDetailsText(String text, String stylename){
        //boolean scrollBarAtEnd = (outputTextPane.getCaretPosition()>outputStyledDoc.getLength()-15);
        boolean scrollBarAtEnd = (setDetailsScrollPane.getVerticalScrollBar().getValue()+setDetailsScrollPane.getVerticalScrollBar().getHeight()>
                setDetailsScrollPane.getVerticalScrollBar().getMaximum()-50);
//        System.out.println(outputScrollPane.getVerticalScrollBar().getValue()+" :: "+outputScrollPane.getVerticalScrollBar().getMaximum());
        try {
            setDetailsStyledDoc.insertString(setDetailsStyledDoc.getLength(), text+"\n\n", setDetailsStyledDoc.getStyle(stylename));
        } catch (BadLocationException ex) {
        }
        if(!haltScrollOnManualUse || scrollBarAtEnd){
            setDetailsTextPane.setCaretPosition(setDetailsStyledDoc.getLength());
        }
    }

    public void clearSetDetailsTextPane(){
        try {
            setDetailsStyledDoc.remove(0, setDetailsStyledDoc.getLength() - 1);
        } catch (BadLocationException ex) {
        }
    }
    public void setMaxGeneration(int maxGeneration){
        this.generationCounter.setText("?/"+maxGeneration);
        this.currentGeneration = 0;
        this.maxGeneration = maxGeneration;
        this.progressBar.setMaximum(maxGeneration);
        this.progressBar.setMinimum(0);
    }
    public void incrementGeneration(){
        this.currentGeneration++;
        this.progressBar.setValue(this.currentGeneration);
        this.generationCounter.setText(this.currentGeneration+"/"+this.maxGeneration);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        graphPanel = new javax.swing.JPanel();
        detailsDisplayPanel = new javax.swing.JPanel();
        setDetailsScrollPane = new javax.swing.JScrollPane();
        setDetailsTextPane = new javax.swing.JTextPane();
        statusBarPanel = new javax.swing.JPanel();
        statusLeftPanel = new javax.swing.JPanel();
        statusRightPanel = new javax.swing.JPanel();
        generationCounter = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        saveGraphMenuItem = new javax.swing.JMenuItem();
        saveResultsMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Optimisation");
        setBackground(new java.awt.Color(255, 255, 255));
        getContentPane().setLayout(new java.awt.GridBagLayout());

        graphPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        graphPanel.setLayout(new java.awt.GridLayout(1, 0));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(graphPanel, gridBagConstraints);

        detailsDisplayPanel.setBackground(new java.awt.Color(255, 255, 255));
        detailsDisplayPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        detailsDisplayPanel.setLayout(new java.awt.GridLayout(1, 0));

        setDetailsScrollPane.setBackground(new java.awt.Color(255, 255, 255));

        setDetailsTextPane.setBackground(new java.awt.Color(255, 255, 255));
        setDetailsTextPane.setEditable(false);
        setDetailsScrollPane.setViewportView(setDetailsTextPane);

        detailsDisplayPanel.add(setDetailsScrollPane);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(detailsDisplayPanel, gridBagConstraints);

        statusBarPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        statusBarPanel.add(statusLeftPanel, gridBagConstraints);

        statusRightPanel.setLayout(new java.awt.GridBagLayout());

        generationCounter.setText("?/?");
        statusRightPanel.add(generationCounter, new java.awt.GridBagConstraints());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        statusRightPanel.add(progressBar, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        statusBarPanel.add(statusRightPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
        gridBagConstraints.weightx = 1.0;
        getContentPane().add(statusBarPanel, gridBagConstraints);

        fileMenu.setText("File");

        saveGraphMenuItem.setText("Save Graph");
        fileMenu.add(saveGraphMenuItem);

        saveResultsMenuItem.setText("Save All");
        fileMenu.add(saveResultsMenuItem);

        menuBar.add(fileMenu);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel detailsDisplayPanel;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JLabel generationCounter;
    private javax.swing.JPanel graphPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JMenuItem saveGraphMenuItem;
    private javax.swing.JMenuItem saveResultsMenuItem;
    private javax.swing.JScrollPane setDetailsScrollPane;
    private javax.swing.JTextPane setDetailsTextPane;
    private javax.swing.JPanel statusBarPanel;
    private javax.swing.JPanel statusLeftPanel;
    private javax.swing.JPanel statusRightPanel;
    // End of variables declaration//GEN-END:variables

}
